import shutil
import subprocess
from pathlib import Path
from typing import Dict, List, Optional, Tuple


class RepoUtils:
    """仓库操作工具类"""

    @staticmethod
    def repo_init(repo_url: str, repo_branch: str, repo_dir: Path) -> bool:
        """执行 repo init 初始化仓库"""
        cmd = [
            "repo", "init",
            "-u", repo_url,
            "-b", repo_branch,
            "--no-repo-verify"
        ]
        print(f"repo init command: {cmd}")
        success, stdout, stderr = CommonUtils.run_command(cmd, repo_dir)

        if success:
            print("✅ repo init 执行成功")
            if stdout.strip():
                print(stdout)
            return True
        else:
            print("❌ repo init 执行失败")
            if stderr.strip():
                print(stderr)
            return False

    @staticmethod
    def repo_sync(repo_dir: Path, project: str = "arkui_ace_engine") -> bool:
        """执行 repo 同步"""
        print("执行 repo sync...")

        cmd = ["repo", "sync", "-c", project]

        success, stdout, stderr = CommonUtils.run_command(cmd, repo_dir, timeout=1800)

        if success:
            print("✅ repo sync 执行成功")
            if stdout.strip():
                print(stdout)
            return True
        else:
            print("❌ repo sync 执行失败")
            if stderr.strip():
                print(stderr)
            return False

    @staticmethod
    def check_and_sync_repo(repo_url: str, repo_branch: str, repo_dir: Path, project: str = "arkui_ace_engine") -> bool:
        """检查并同步代码仓库"""
        repo_dir = repo_dir / ".repo"

        if repo_dir.is_dir():
            print("检测到已有 .repo 目录，执行 repo sync...")
            return RepoUtils.repo_sync(repo_dir, project)
        else:
            print("未检测到 .repo 目录，执行 repo init...")
            if RepoUtils.repo_init(repo_url, repo_branch, repo_dir):
                return RepoUtils.repo_sync(repo_dir, project)
            else:
                return False


class CommonUtils:
    """通用工具类"""

    @staticmethod
    def run_command(cmd: List[str], cwd: Optional[Path] = None,
                    timeout: int = 600) -> Tuple[bool, str, str]:
        """
        运行命令并返回结果

        Args:
            cmd: 命令列表
            cwd: 工作目录
            timeout: 超时时间（秒）

        Returns:
            (成功标志, 标准输出, 标准错误)
        """
        try:
            result = subprocess.run(
                cmd,
                cwd=cwd,
                capture_output=True,
                text=True,
                timeout=timeout
            )

            if result.returncode == 0:
                return True, result.stdout, result.stderr
            else:
                return False, result.stdout, result.stderr

        except subprocess.TimeoutExpired:
            error_msg = f"命令执行超时: {' '.join(cmd)}"
            print(error_msg)
            return False, "", error_msg
        except Exception as e:
            error_msg = f"执行命令时发生异常: {str(e)}"
            print(error_msg)
            return False, "", error_msg

    @staticmethod
    def run_python_analysis(work_dir: Path, script_path: str) -> bool:
        """执行 Python 分析脚本"""
        if not Path(script_path).is_file():
            print(f"❌ 分析脚本不存在: {script_path}")
            return False

        print("开始执行代码分析...")

        cmd = [
            "python",
            script_path,
            "foundation/arkui/ace_engine/",
            "--exclude_dirs", "foundation/arkui/ace_engine/test",
            "foundation/arkui/ace_engine/adapter/preview/",
            "--include_dirs", "foundation/arkui/ace_engine/",
            "foundation/arkui/ace_engine/frameworks/",
            "foundation/arkui/ace_engine/interfaces/inner_api/ace_kit/include/"
        ]

        success, stdout, stderr = CommonUtils.run_command(cmd, work_dir)

        if success:
            print("✅ 代码分析执行成功")
            if stdout.strip():
                print(f"分析输出:\n{stdout}")
            return True
        else:
            print("❌ 代码分析执行失败")
            if stderr.strip():
                print(f"错误输出:\n{stderr}")
            return False

    @staticmethod
    def backup_analysis_results(master_dir: Path, base_dir: Path, diff_dir: str) -> bool:
        """备份分析结果到基础目录"""
        foundation_dir = master_dir / "foundation"
        txt_file = master_dir / "hfile_counts.txt"
        base_foundation_dir = base_dir / "foundation"

        success = True

        # 拷贝 foundation 目录
        if foundation_dir.is_dir():
            if not CommonUtils.copy_files(foundation_dir, base_foundation_dir):
                success = False
        else:
            print(f"⚠️ foundation 目录不存在: {foundation_dir}")

        # 拷贝分析结果文件
        if txt_file.is_file():
            if not CommonUtils.copy_files(txt_file, diff_dir / txt_file.name):
                success = False
        else:
            print(f"⚠️ 分析结果文件不存在: {txt_file}")

        return success

    @staticmethod
    def copy_files(src: Path, dst: Path) -> bool:
        """
        拷贝文件或目录（强制覆盖）

        Args:
            src: 源路径
            dst: 目标路径

        Returns:
            True 如果拷贝成功，False 如果失败
        """
        try:
            if src.is_dir():
                # 如果目标目录已存在，先删除它
                if dst.exists():
                    shutil.rmtree(dst)
                    print(f"♻️ 已删除目标目录: {dst}")
                shutil.copytree(src, dst)
                print(f"✅ 成功拷贝目录: {src} -> {dst}")
                return True
            elif src.is_file():
                # 确保目标目录存在
                dst.parent.mkdir(exist_ok=True, parents=True)
                # 对于文件，直接使用 copy2 会覆盖同名文件
                shutil.copy2(src, dst)
                print(f"✅ 成功拷贝文件: {src} -> {dst}")
                return True
            else:
                print(f"⚠️ 源路径不存在: {src}")
                return False
        except Exception as e:
            print(f"❌ 拷贝失败: {str(e)}")
            return False